package auxiliares {
	import avmplus.FLASH10_FLAGS;
	
	import flash.display.DisplayObject;
	import flash.display.FrameLabel;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import mx.charts.chartClasses.InstanceCache;
	import mx.containers.Canvas;
	import mx.controls.Image;
	import mx.effects.Effect;
	import mx.effects.Move;
	import mx.effects.Rotate;
	import mx.effects.easing.Sine;
	import mx.events.EffectEvent;

	/**
	 * 
	 * @author mcustiel
	 * 
	 */
	public class Grafico {
		private static const DEFAULT_XPOS:int = 0;
		private static const DEFAULT_YPOS:int = 0;
		private static const DEFAULT_ANCHO:int = 10;
		private static const DEFAULT_ALTO:int = 10;
		private static const DEFAULT_N_PIXELS:int = 50;
		private static const DEFAULT_N_PIXELS_ROTATE:int = 20;
		
		private var ancho:Number;
		private var alto:Number;
		private var xPos:Number;
		private var yPos:Number;
		private var angulo: Number;
		private var timePixel: Number;
		private var timePixelRotate: Number;
		private var velocidad: Number;
		
		protected var contenedorImagen: Canvas;
		protected var imagen: Image;
		private var move: Move;
		private var rotate:Rotate;
		private var colFuncion : Function;
		protected var eliminarFunction: Function = null;
		protected var borrar: Number = 0;
		protected var stoped: Boolean = false;
		protected var enMovimiento: Boolean = false;
		protected var enRotacion: Boolean = false;
		protected var posColision: Coordenada = new Coordenada();
		/**
		 * 
		 * @param _contenedor
		 * @param _imagen
		 * @param _xPos
		 * @param _yPos
		 * @param _ancho
		 * @param _alto
		 * 
		 */
		public function Grafico(_contenedor:Canvas, _imagen: Object,
								_xPos:Number = DEFAULT_XPOS, _yPos:Number = DEFAULT_YPOS,
								_ancho:Number = DEFAULT_ANCHO, _alto:Number = DEFAULT_ALTO) {
			//trace("Construyendo gráfico: x: " + _xPos + " - y: " + _yPos + " - ancho: " + _ancho + " - alto: " + _alto);

			ancho = _ancho
			alto = _alto;
			xPos = _xPos;
			yPos = _yPos;
			angulo = 0;
			velocidad = new Number();
			
			imagen = new Image();
			imagen.load(_imagen);
			imagen.x = -(ancho/2);
			imagen.y = -(alto/2);
			imagen.scaleContent = false;
			imagen.maintainAspectRatio = true;
			
			contenedorImagen = new Canvas();
			contenedorImagen.clipContent = false;
			contenedorImagen.x = xPos;
			contenedorImagen.y = yPos;
			contenedorImagen.addChild(imagen);
			
			move = new Move(contenedorImagen);
			move.easingFunction = Sine.easeOut;
			move.addEventListener(EffectEvent.EFFECT_START, setIsMoving);
			move.addEventListener(EffectEvent.EFFECT_END, setIsNotMoving);
				
			rotate = new Rotate(contenedorImagen);
			rotate.easingFunction = Sine.easeOut;
			rotate.addEventListener(EffectEvent.EFFECT_START, setIsRotating);
			rotate.addEventListener(EffectEvent.EFFECT_END, setIsNotRotating);
			
			_contenedor.addChild(contenedorImagen);
		}
		
		/**
		 * 
		 * @param _newX
		 * @param _newY
		 * 
		 */
		public function posicionar(_newX: Number, _newY: Number, _grad:Number=-1): void {
			xPos = _newX;
			yPos = _newY;
			
			contenedorImagen.x = xPos;
			contenedorImagen.y = yPos;
			
			if ( _grad != -1 ) {
				setRotation(_grad);
			}
			
		}
		
		public function setRotation(_grad:Number): void {
			angulo = _grad;
			contenedorImagen.rotation = angulo;
		}

		/**
		 * 
		 * @param _newX
		 * @param _newY
		 * 
		 */
		public function mover(_newX:Number, _newY:Number): void {
			var ang: Number = calcularAngulo(_newX, _newY);
			rotar(ang, function respuesta (_event: EffectEvent): void {

				var time:Number = Math.max(1, Math.round(Math.sqrt(Math.pow(xPos - _newX, 2) + Math.pow(yPos - _newY, 2)) / DEFAULT_N_PIXELS) * timePixel);
				//trace ("MOVIENDO A : " + _newX);
				/*if ( move.isPlaying )*/ move.end();
				move.xTo = xPos = _newX;
				move.yTo = yPos = _newY;
				move.duration = time;
				//trace(time);
				move.play();

				rotate.removeEventListener(EffectEvent.EFFECT_END, respuesta);
			});
		}
		
		public function actualizarPosicion(): void{
			var oldX:Number = contenedorImagen.x;
			var oldY:Number = contenedorImagen.y;
			posicionar(oldX, oldY);
			
			var rotation:Number = Math.round(contenedorImagen.rotation);
			if ( rotation < 0 ) {
				rotation = rotation + 360;
			}
			setAngulo(rotation);
		}
		
		/**
		 * 
		 * @param _xDirectriz
		 * @param _yDirectriz
		 * 
		 */
		public function rotar(_angulo: Number, _callback: Function = null): void {
			var anguloRelativo:Number = _angulo;
			
			if ( angulo >= 180 + _angulo ) {
				anguloRelativo = 360 + _angulo;
			} else if ( angulo + 180 < _angulo ) {
				anguloRelativo = _angulo - 360;
			}
			
			if (_callback != null) {
				rotate.addEventListener(EffectEvent.EFFECT_END, _callback);
			}
			
			var time:Number = Math.max(1, Math.round( (Math.abs(angulo + (anguloRelativo * -1)) / DEFAULT_N_PIXELS_ROTATE) * timePixelRotate));
			//trace(time);
			/*if ( rotate.isPlaying )*/ rotate.end();
			rotate.angleFrom = angulo;
			rotate.angleTo = anguloRelativo;
			rotate.originX = 0;
			rotate.originY = 0;
			rotate.duration = time;
			angulo = _angulo;
			rotate.play();
		}
		
		public function virar(_xDirectriz:Number, _yDirectriz:Number, _callback: Function = null): void {
			
			var anguloCalculado:Number = calcularAngulo(_xDirectriz, _yDirectriz);
			var anguloRelativo:Number = anguloCalculado;
			
			if ( angulo >= 180 + anguloCalculado ) {
				anguloRelativo = 360 + anguloCalculado;
			} else if ( angulo + 180 < anguloCalculado ) {
				anguloRelativo = anguloCalculado - 360;
			}

			if (_callback != null) {
				rotate.addEventListener(EffectEvent.EFFECT_END, _callback);
			}

			var time:Number = Math.max(1, Math.round( (Math.abs(angulo + (anguloRelativo * -1)) / DEFAULT_N_PIXELS_ROTATE) * timePixelRotate));
			if ( rotate.isPlaying ) rotate.end();
			rotate.angleFrom = angulo;
			rotate.angleTo = anguloRelativo;
			rotate.originX = 0;
			rotate.originY = 0;
			rotate.duration = time;
			angulo = anguloCalculado;
			rotate.play();
		}
		
		/**
		 * 
		 * @param _xDirectriz
		 * @param _yDirectriz
		 * @return Number
		 * 
		 */
		public function calcularAngulo(_xDirectriz:Number, _yDirectriz:Number): Number {
			var distX:Number = (_xDirectriz - xPos), distY:Number = (_yDirectriz - yPos); 
			var tan:Number = Math.atan(distY/distX);
			var grados:Number = Math.round( tan * (180/Math.PI) );
			
			if (xPos < _xDirectriz) {
				if (yPos > _yDirectriz) {
					grados = 360 + grados;
				}
			} else if(xPos > _xDirectriz) {
				grados += 180;
			}
			//grados de 0 a 360 sentido horario
			return grados;
		}
		
		public function getVelocidad():Number {
			return velocidad;
		}
		
		public function setVelocidad(value:Number):void {
			velocidad = value;
		}
		
		public function getXPos(): Number {
			//return xPos;
			return contenedorImagen.x;
		}
		
		public function getYPos(): Number {
			//return yPos;
			return contenedorImagen.y;
		}
		
		public function getAngulo(): Number {
			return angulo;
		}
		
		public function getAncho(): Number {
			return ancho;
		}
		
		public function getAlto(): Number {
			return alto;
		}
		
		public function getObject(): DisplayObject {
			return imagen;
		}
		
		public function setAncho(_ancho:Number): void {
			ancho = _ancho;
		}
			
		public function setAlto(_alto:Number): void {
			alto = _alto;
		}
		
		public function setAngulo(_angulo:Number): void{
			angulo = _angulo;
		}
		
		public function setVisible(_visible:Boolean): void{
			contenedorImagen.visible = _visible;
		}
		
		public function isVisible(): Boolean{
			return contenedorImagen.visible;
		}
		
		public function setIsMoving(_event:EffectEvent=null): void{
			enMovimiento = true;
		}
		
		public function setIsNotMoving(_event:EffectEvent=null): void{
			enMovimiento = false;
		}
		
		public function isMoving(): Boolean{
			return move.isPlaying;
		}
		
		public function setIsRotating(_event:EffectEvent=null): void{
			enRotacion = true;
		}
		
		public function setIsNotRotating(_event:EffectEvent=null): void{
			enRotacion = false;
		}
		
		public function isRotating(): Boolean{
			return rotate.isPlaying;
		}
		
		public function setStopped(_flag:Boolean): void{
			stoped = _flag;
		}
		
		public function setPosColsion(_coor:Coordenada): void{
			posColision = _coor;
		}
		
		public function getPosColsion(): Coordenada{
			return posColision;
		}
		
		public function isStopped(): Boolean{
			return stoped;
		}
		
		public function setFuncionInicioMovimiento(_func:Function): void{
			move.addEventListener(EffectEvent.EFFECT_START, _func);
		}
		
		public function setFuncionFinMovimiento(_func:Function): void{
			move.addEventListener(EffectEvent.EFFECT_END, _func);
		}
		
		public function setTimePixel( _time:Number): void {
			timePixel = _time;
		}
		
		public function getTimePixel(): Number {
			return timePixel;
		}
		
		public function setTimePixelRotate( _time:Number): void {
			timePixelRotate = _time;
		}
		
		public function getTimePixelRotate(): Number {
			return timePixelRotate;
		}
		
		public function getNombre(): String {
			return contenedorImagen.name;
		}
		
		public function getId(): String {
			return contenedorImagen.id;	
		}
		
		public function stopMove(): Boolean {
			if ( move.isPlaying ) {
				move.stop();
				actualizarPosicion();
				return true;
			} else {
				return false;
			}
		}
		
		public function stopRotate(): Boolean {
			if ( rotate.isPlaying ) {
				rotate.stop();
				actualizarPosicion();
				return true;
			} else {
				return false;
			}
		}
		
		public function setEliminarFunction(_eliminarfunc: Function):void {
			eliminarFunction = _eliminarfunc;
		}
		
		public function setFunctionColision(_funcion:Function): void {
			colFuncion = _funcion;
			rotate.addEventListener(EffectEvent.EFFECT_START, setStartListener);
			move.addEventListener(EffectEvent.EFFECT_START, setStartListener);
			rotate.addEventListener(EffectEvent.EFFECT_END, setEndRotateListener);
			move.addEventListener(EffectEvent.EFFECT_END, setEndMoveListener);
		}
		
		public function setStartListener(_event:EffectEvent): void {
			imagen.addEventListener(Event.ENTER_FRAME, colFuncion);
		}
		
		public function setEndRotateListener(_event:EffectEvent): void {
			imagen.removeEventListener(Event.ENTER_FRAME, colFuncion);
		}
		
		public function setEndMoveListener(_event:EffectEvent): void {
			imagen.removeEventListener(Event.ENTER_FRAME, colFuncion);
		}
		
		public function setMoveListener(_funcion:Function): void {
			imagen.addEventListener(Event.ENTER_FRAME, _funcion);
		}
		
		public function cambiarImagen(_imagen:Object):void {
			imagen.load(_imagen);
		}
		
		public function setBorrar( _borrar:Number ):void {
			borrar = _borrar;
		}
		
		public function paraBorrar():Number {
			return borrar;			
		}
		public function eliminar(_type:String = null):void {
			contenedorImagen.parent.removeChild(contenedorImagen);	
		}
	}
}